#define I686
#include <stdlib.h>
#include "semaphore.h"
#include "thread.h"
#include "spinlock.h"
#include "ring_thread_list.h"

struct semaphore {
   unsigned int size ;    
   unsigned int holding;   //nb threads holding the semaphore

   struct list * waiting ;
   spinlock_t lock;
};
   
struct semaphore * init_semaphore(unsigned int size){
   if(size == 0)
      return NULL;
   struct semaphore *sem ;
   sem=malloc(sizeof (struct semaphore));
   sem->size    = size ;
   sem->holding = 0 ;
   spin_unlock(&sem->lock);
   sem->waiting=NULL;
   return sem;
}

void wait_semaphore(struct semaphore * sem){
   int key = 0;
   spin_lock(&sem->lock);
   key = (sem->holding < sem->size) ;
   if(key)
	   sem->holding++;
   spin_unlock(&sem->lock);

   if(!key){
      thread_t self = thread_self();
      insert(sem->waiting,self);
      thread_yield();
   }
}


void post_semaphore(struct semaphore * sem){
   int release = 0;
   spin_lock(&sem->lock);
      release = (sem->holding> 0);
      if(release) sem->holding--;
   spin_unlock(&sem->lock);

   if(release) {
      thread_t th = head(shift(sem->waiting));
      if(th!=NULL)
         add_thread_runq(th);
   }
}


void free_semaphore(struct semaphore * sem){
	free_list(sem->waiting);
   free(sem);
}

